#include "game.h"
#include "date.h"
#include "mywindows.h"
#include <conio.h>
#include <mmsystem.h>
#pragma comment(lib,"Winmm.lib")

int grade=0;  ///分数
int level=1;  ///等级
int one=0;
int two=0;
int three=0;
int four=0;


BLOCK cur_block;  ///当前方块
BLOCK next_block;  ///下个方块



///绘制游戏边框
void windowPrint(int x,int y)
{
    int i,j;
    for(i=0;i<25;i++)
    {
        for(j=0;j<26;j++)
        {
            if(windowShape[i][j]==1)
            {
                setColor(0xc0);
                setPos(x+j,y+i);
                printf("%2s","");  //-->printf("  ");
            }
        }
    }
}

///操作规则
void printInfo()
{
    setColor(0x0a);

    setPos(31,9);
    printf("操作规则:");
    setPos(31,10);
    printf("按 a 或 A 左移");
    setPos(31,11);
    printf("按 d 或 D 右移");
    setPos(31,12);
    printf("按 s 或 S 下移");
    setPos(31,13);
    printf("按 w 或 W 变形");
    setPos(31,14);
    printf("按 回车 直接下落");
    setPos(31,15);
    printf("按 空格 暂停");
}


///分数等级
void printGradeLevel(int num)
{
    switch(num)
    {
        case 0:
            break;
        case 1:
            grade+=20;break;
        case 2:
            grade+=40;break;
        case 3:
            grade+=60;break;
        case 4:
            grade+=80;break;
    }
    ///设置等级
    if(grade < 100) {level=1;}
    else if(grade>=100&&grade<300) {level=2;}
    else if(grade>=300&&grade<500) {level=3;}
    else if(grade>=500&&grade<800) {level=4;}
    else if(grade>=800&&grade<1000) {level=5;}
    else if(grade>=1000&&grade<1200) {level=6;}
    else if(grade>=1200&&grade<1400) {level=7;}
    else if(grade>=1400&&grade<1600) {level=8;}
    else if(grade>=1600&&grade<1800) {level=9;}
    else if(grade>=1800&&grade<2000) {level=10;}
        setColor(0x09);
        setPos(3,4);
        printf("Score:%d",grade);
        setPos(3,5);
        printf("Level:%d",level);

        ///提示信息
        setPos(3,6);
        if(level==1){printf("FIRST BLOOD!");}
        else if(level==2){printf("DOUBLE KILL!");}
        else if(level==3){printf("TRIPLE KILL!");}
        else if(level==4){printf("QUADRA KILL!");}
        else if(level==5){printf("PENTA KILL!");}
        else if(level==6){printf("LEGENDARY!");}
        else if(level==7){printf("UNBREAKABLE!");}
        else if(level==8){printf("UNBELIEVABLE!");}
        else if(level==9){printf("COME GET SOME!");}
        else if(level==10){printf("GOD LIKE!!");}

}

///左边框
void leftBorder(int x,int y)
{
    int a,b;
    for(a=0;a<13;a++)
    {
        for(b=0;b<10;b++)
        {
            if(left[a][b] == 1)
            {
                setColor(0x09);
                setPos(x+b,y+a);
                printf("■");
            }
        }
    }
}

///计时器
void gameTime(clock_t start_time)
{
    setColor(0x0c);
    setPos(3,3);
    printf("游戏已运行 %ld s",(clock()-start_time)/CLOCKS_PER_SEC);
}

///打印方块
void printBlock(int x,int y,int shape,int status, int color)
{
int i,j;
for(i=0;i<4;i++)
{
    for(j=0;j<4;j++)
    {
        if(block[shape][status][i][j]==1)
        {
            setColor(color);
            setPos(x+j,y+i);
            printf("■");
    }
}
}
}

///删除方块
void deleteBlock(int x,int y,int shape,int status){
    int i,j;
    for(i=0;i<4;i++){
        for(j=0;j<4;j++){
            if(block[shape][status][i][j]==1){
                setPos(x+j,y+i);
                printf("%2s","");
            }
        }
    }
}

///第一个方块
void startBlock()
{
   ///第一个方块:形状/形态-->随机  位置（x,y)固定的
   ///初始化cur_block
   ///设置随机数种子（时间永远不一样）
   srand((unsigned)time(NULL));
   cur_block.x=22;
   cur_block.y=1;
   cur_block.shape=rand()%7;
   cur_block.status=rand()%4;
   cur_block.color=rand()%0x10;  ///0x00-0x0f
   ///如果随机产生的颜色是黑色，把颜色设置成白色
   if(cur_block.color==0x00)
   {
       cur_block.color=0x0f;
   }
   printBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status,cur_block.color);
}

///下一个方块
void nextBLOCK()
{
///形态/形状/颜色--->随机，位置--->固定
deleteBlock(next_block.x,next_block.y,
                next_block.shape,next_block.status);
next_block.x=34;
next_block.y=2;
next_block.shape=rand()%7;
next_block.status=rand()%4;
next_block.color=rand()%0x10;;
if(next_block.color==0x00)
   {
       next_block.color=0x0f;
   }
   printBlock(next_block.x,next_block.y,next_block.shape,next_block.status,next_block.color);
}

///复制方块
void copyBLOCK()
{
///当前方块=下一个方块，并产生新的"下一个方块"
///初始化next_block值
cur_block=next_block;
cur_block.x=22;
cur_block.y=1;
printBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status,cur_block.color);
nextBLOCK();
}

///下移方块
int downBLOCK()
{
    ///原理：删除正在显示的方块，纵坐标加1，重新打印
    if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status)==-1)
    {
        ///发生碰撞：方块落底游戏池底部
        ///产生新的方块：下一个方块值->当前正在下落的方块，重新产生下一个方块
        save();
        lineClear();
        UpdateGame();
        copyBLOCK();
        return -1;
    }else if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status)==-2)
    {
        ///游戏结束
        return -2;
    }else{
    deleteBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status);
    cur_block.y+=1;
    printBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status,cur_block.color);
    return 0;}
}

///左移方块
void leftBLOCK(){
    if(crash(cur_block.x-1,cur_block.y,cur_block.shape,cur_block.status)==-1)
   {
       ///发生碰撞什么都不做，直接返回
       return;
   }
    deleteBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status);
    cur_block.x-=1;
    printBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status,cur_block.color);
    return 0;
}

///右移方快
void rightBLOCK(){
     if(crash(cur_block.x+1,cur_block.y,cur_block.shape,cur_block.status)==-1)
    {
        ///发生碰撞什么都不做，直接返回
        return;
    }
    deleteBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status);
    cur_block.x+=1;
    printBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status,cur_block.color);
    return 0;
}

///方块变形
void  changeBlock()
{
    ///通过数组下标+1获得下一个形态，下标[0-3]
   if(crash(cur_block.x,cur_block.y,cur_block.shape,(cur_block.status+1)%4)==-1)
    {
       return;
    }
    deleteBlock(cur_block.x,cur_block.y,cur_block.shape,cur_block.status);
    cur_block.status = (cur_block.status+1)%4;
    printBlock(cur_block.x,cur_block.y,cur_block.shape,
               cur_block.status,cur_block.color);
}

///碰撞检测
int crash(int x,int y,int shape,int status)
{
    int i,j;
    for(i=0;i<4;i++)
    {
       for(j=0;j<4;j++)
       {
         if(block[shape][status][i][j]==1)
         {
            if(windowShape[i+y][j+x-15]==1)
            {
                ///发生碰撞
                if(cur_block.x==22&&cur_block.y==1)
                {
                    ///方块产生就发生碰撞，游戏结束
                    return -2;
                }
                ///方块落到游戏池底，发生碰撞
                return -1;

            }
         }
       }
    }
    return 0;
}

///保存方块
void save()
{///根据方块在界面上的坐标，把坐标对应到游戏池的下标的对应位置
 ///方块为1的保存到windowShape数组
    int i,j;
    for(i=0;i<4;i++)
        {
        for(j=0;j<4;j++)
            {
            if(block[cur_block.shape][cur_block.status][i][j]==1){
                windowShape[i+cur_block.y][j+cur_block.x-15]=1;
            }
        }
    }
}

///刷新游戏池
void UpdateGame()
{
    int i,j;
    for(i=23;i>0;i--)
    {
        for(j=1;j<15;j++)
        {
            if(windowShape[i][j]==1)
            {
                setColor(0x0e);
                setPos(15+j,i);
                printf("■");
            }else{
                setColor(0x00);
                setPos(15+j,i);
                printf("%2s","");
            }
        }
    }
}

///暂停
void pause()
{
    while(1)
    {
        if(getch()==32)
        {
            break;
        }
    }
}

///方快直接落底
void bottomBlock()
{
    while(1)
    {


        if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status)== -1)
        {
        save();
        UpdateGame();
        copyBLOCK();
        return;
        }else  if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status)== -2)
                {
                    ///游戏结束
                    return;
                }else{
                ++cur_block.y;
        }
    }
}

///消行检测
void lineClear()
{
    ///遍历windowShape,判断是否有满行:这行所有值加起来为14
    int i,j;
    int number=0;
    for(i=23;i>0;i--)
    {
        int total = 0;
        for(j=1;j<15;j++)
        {
            total += windowShape[i][j];
        }
        if(14 == total)
        {
            lineDown(i);
            i += 1;
            ///统计一次消几行
            number+=1;
        }
    }
    printGradeLevel(number);
    lineClearNum(number);
}

///统计消行提示
lineClearNum(int num)
{
    switch(num)
    {
        case 0:
               break;
        case 1:
            one+=1;break;
        case 2:
            two+=2;break;
        case 3:
            three+=3;break;
        case 4:
            four+=4;break;
    }
        setPos(3,7);
        printf("消除一行次数：%d",one);
         setPos(3,8);
        printf("消除两行次数：%d",two);
         setPos(3,9);
        printf("消除三行次数：%d",three);
         setPos(3,10);
        printf("消除四行次数：%d",four);
    }



///消行下移动
void lineDown(int line)
{
    ///从第line行开始,i = i-1
    int i,j;
    for(i=line;i>1;i--)     ///i>1,保证边界不被下移
    {
        for(j=1;j<15;j++)
        {
            windowShape[i][j] = windowShape[i-1][j];
        }
    }
}

///游戏结束动画
void printOver()
{
    int i,j;
    for(i=23;i>0;i--)
    {
        for(j=1;j<15;j++)
        {
            setColor(0x76);
            setPos(j+15,i);
            printf("★");
            Sleep(5);
        }
    }
}

///重新开始提示
void printFinish()
{
setColor(0x0d);
setPos(20,8);
printf("游戏结束！");
setPos(17,9);
printf("按Y重新开始");
setPos(23,9);
printf("按N结束游戏");
  switch(getch())
  {
  case 'Y':
  case 'y':
    againGame();break;
  case 'n':
  case 'N':
      ///关闭音乐
      mciSendString(TEXT("stop a"),NULL, 0,NULL);
    break;
  default:
    printFinish();break;
  }
}

///重新开始游戏
void againGame()
{
  ///重置分数、等级、游戏池数据->开始游戏
  level=1;
  grade=0;

  ///重置游戏池数组
  int i,j;
  for(i=1;i<24;i++)
  {
      for(j=1;j<15;j++)
      {
          windowShape[i][j]=0;
      }
  }
  setColor(0x00);
  system("cls");  ///清屏
  gameInit();
}

///打印开始界面
void printStart(int x,int y)
{
    int color=rand()%0x10;
    if(color==0x10)
    {
        color=0x0f;
    }

    ///绘制图案
    setColor(color);
    setPos(x,y);
    printf("■■■■■  ■■■■■  ■■■■■  ■■■■  ■■■  ■■■■");
    setPos(x,y+1);
    printf("    ■      ■              ■      ■    ■    ■    ■");
    setPos(x,y+2);
    printf("    ■      ■■■■        ■      ■■■■    ■    ■■■■");
    setPos(x,y+3);
    printf("    ■      ■              ■      ■  ■      ■          ■");
    setPos(x,y+4);
    printf("    ■      ■■■■■      ■      ■    ■  ■■■  ■■■■");

    setPos(25,15);
    printf("按任意键开始游戏！");
}

///清除开始动画
void deleteStart(int x,int y)
{
    int i,j;
    for(i=y;i<=y+4;i++)
    {
        for(j=x;j<=x+33;j++)
        {
            setPos(j,i);
            printf("%2s","");

        }
    }
}

///动画效果->定时（边界控制）
void printAnimation()
{
    clock_t time1,time2;
    time1 =clock();
    int x=5;
    printStart(x,5);
    while(1)
    {
        time2 =clock();
        if(time2-time1>300)    ///时间间隔300毫秒
        {
            time1 =time2;
            deleteStart(x,5);
            printStart(++x,5);
            if(25==x)
            {
                deleteStart(x,5);
                x=5;
            }
        }
        ///按任意键退出：检查是否有按键输入，若有返回一个非0值，否则返回0
        if(kbhit())
        {
            break;
        }
    }
    system("cls");
}








///主
void gameInit()
{
    ///初始化句柄，必须放在最开始
    initHandle();

    ///打开音乐文件
    mciSendString("open D:\\CodeBlocksworks\\tetris\\bin\\Debug\\res\\俄罗斯方块游戏背景音乐.mp3 alias a",NULL,0,NULL);

    ///播放音乐
    mciSendString(TEXT("play a"),NULL,0,NULL);

    ///开始动画
    printAnimation();
    printInfo();
    windowPrint(15,0);///打印游戏池和边框
    printGradeLevel(0);
    leftBorder(2,2);///打印左边边框
    ///游戏开始时间
    clock_t startTime=clock();
    ///定时器
    clock_t time1,time2;
    time1=clock();



    startBlock();
    nextBLOCK();


    while(1){
        ///检测是否有按键按下
        if(kbhit())
        {
            switch(getch())
            {
                ///方块变形
            case 'w':
            case 'W':
            case 72:
                changeBlock();break;//变形
            case 'a':
            case 'A':
            case 75:
                leftBLOCK();break;//左移
            case 's':
            case 'S':
            case 80:
                downBLOCK();break;//下移
            case 'd':
            case 'D':
            case 77:
                rightBLOCK();break;//右移
            case 32:
                pause();break;//暂停
            case 13:
                bottomBlock();break;//方块落底
            }
        }

        ///下落
      time2=clock();
      ///没0.45s下落一次
      ///（time2-time1）/CLOCKS_PRE_SEC>0.45
       if(time2-time1>0.75*CLOCKS_PER_SEC)
       {
           ///游戏计时
           gameTime(startTime);
           if(downBLOCK()==-2)
           break;
           time1=time2;
       }
    }
    printOver();
    printFinish();
    againGame();

}















